home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / Resources / CutePDF 2.3 / converter.exe / GNUGS / PDF_MAIN.PS < prev    next >
Text File  |  2003-01-29  |  25KB  |  813 lines

  1. %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: pdf_main.ps,v 1.35.2.7.2.2 2003/01/28 11:54:11 ghostgum Exp $
  14. % pdf_main.ps
  15. % PDF file- and page-level operations.
  16.  
  17. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  18. .currentglobal true .setglobal
  19. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  20. pdfdict begin
  21.  
  22. % Patch in an obsolete variable used by some third-party software.
  23. /#? false def
  24.  
  25. % Test whether the current output device handles pdfmark.
  26. /.writepdfmarkdict 1 dict dup /pdfmark null put readonly def
  27. /.writepdfmarks {    % - .writepdfmarks <bool>
  28.   currentdevice //.writepdfmarkdict .getdeviceparams
  29.   mark eq { false } { pop pop true } ifelse
  30.   systemdict /DOPDFMARKS known or 
  31. } bind def
  32.  
  33. % For simplicity, we use a single interpretation dictionary for all
  34. % PDF graphics execution, even though this is too liberal.
  35. /pdfopdict mark
  36.   objopdict { } forall
  37.   drawopdict { } forall
  38.   /endstream { exit } bind
  39.   (%%EOF) cvn { exit } bind        % for filters
  40.     % PDF 1.1 operators
  41.   /BX { /BXlevel BXlevel 1 add store } bind
  42.   /EX { /BXlevel BXlevel 1 sub store } bind
  43.   /PS { cvx exec } bind
  44.     % PDF 1.2 operators
  45.   /BMC { pop } bind
  46.   /BDC { pop pop } bind
  47.   /EMC { }
  48.   /MP { pop } bind
  49.   /DP { pop pop } bind
  50. .dicttomark readonly def
  51.  
  52. % ======================== Main program ======================== %
  53.  
  54. end            % pdfdict
  55. userdict begin
  56.  
  57. /defaultfontname /Times-Roman def
  58.  
  59. % Make sure the registered encodings are loaded, so we don't run the risk
  60. % that some of the indices for their names will overflow the packed
  61. % representation.  (Yes, this is a hack.)
  62. SymbolEncoding pop
  63. DingbatsEncoding pop
  64.  
  65. % Redefine 'run' so it recognizes PDF files.
  66. systemdict begin
  67. /.runps /run load def
  68. /run {
  69.   dup type /filetype ne { (r) file } if
  70.   dup ( ) .peekstring {
  71.     (%) eq {
  72.       dup (     ) .peekstring {
  73.     (%PDF-) eq {
  74.         dup (%stdin) (r) file eq {
  75.           % Copy PDF from stdin to temporary file then run it.
  76.           null (w+) //systemdict /.tempfile get exec exch 3 1 roll
  77.           % stack: tempname stdin tempfile
  78.           1024 string
  79.           {
  80.         % stack: tempname stdin tempfile string
  81.         2 index 1 index readstring
  82.         exch 3 index exch writestring
  83.         not { exit } if
  84.           }
  85.           loop
  86.           pop exch closefile
  87.           % stack: tempname tempfile
  88.           dup 0 setfileposition
  89.           dup runpdf
  90.           closefile deletefile
  91.         } {
  92.           runpdf
  93.         } ifelse
  94.       } {
  95.         cvx .runps % doesn't start with %PDF-
  96.       } ifelse
  97.     } {
  98.       pop cvx .runps % didn't read 5 characters
  99.     } ifelse
  100.     } {
  101.       cvx .runps % didn't start with %
  102.     } ifelse
  103.   } {
  104.     pop closefile % file was empty
  105.   } ifelse
  106. } bind odef
  107. currentdict /runpdfstring .undef
  108.  
  109. /runpdf {        % <file> runpdf -
  110.    userdict begin
  111.     % It turns out that the PDF interpreter uses memory more
  112.     % effectively if it is run under at least one level of save.
  113.     % This is counter-intuitive, and we don't understand why it happens,
  114.     % but the improvement is significant.
  115.    /PDFTopSave save def
  116.    /Page# null def
  117.    /Page null def
  118.    /DSCPageCount 0 def
  119.    /PDFSave null def
  120.    GS_PDF_ProcSet begin
  121.    pdfdict begin
  122.    pdfopen begin
  123.    Trailer /Root oget /Pages oget /CropBox knownoget
  124.     { mark /CropBox 3 -1 roll /PAGES pdfmark
  125.     }
  126.    if
  127.    /FirstPage where 
  128.     { pop FirstPage dup pdfpagecount gt
  129.       { (\nRequested FirstPage is greater than the number of pages in the file: ) print
  130.         pdfpagecount = flush
  131.       } if
  132.     } {
  133.       1
  134.     } ifelse
  135.    1
  136.    /LastPage where { pop LastPage pdfpagecount .min } { pdfpagecount } ifelse
  137.    2 index 1 index gt
  138.     { (   No pages will be processed \(FirstPage > LastPage\).) = flush }
  139.     { QUIET not
  140.       { (Processing pages ) print 2 index =only ( through ) print dup =only
  141.         (.) = flush
  142.       }
  143.      if
  144.     }
  145.    ifelse
  146.     { dup /Page# exch store
  147.       QUIET not { (Page ) print dup == flush } if
  148.       pdfgetpage pdfshowpage
  149.     } for
  150.    currentdict pdfclose
  151.    end            % temporary dict
  152.    end            % pdfdict
  153.    end            % userdict
  154.    end            % GS_PDF_ProcSet
  155.    PDFTopSave restore
  156. } bind def
  157. end            % systemdict
  158. % Redefine the procedure that the C code uses for running piped input.
  159. % It is OK to use { (%stdin) run } here, because a startjob cannot occur.
  160. /.runstdin {
  161.   { (%stdin) run } execute0
  162. } bind def
  163.  
  164. end            % userdict
  165. pdfdict begin
  166.  
  167. % ======================== File parsing ======================== %
  168.  
  169. % Read the cross-reference and trailer sections.
  170.  
  171. /traileropdict mark
  172.   (<<) cvn { mark } bind
  173.   (>>) cvn /.dicttomark load
  174.   ([) cvn { mark } bind        % ditto
  175.   (]) cvn dup load
  176. %  /true true        % see .pdfexectoken in pdf_base.ps
  177. %  /false false        % ibid.
  178. %  /null null        % ibid.
  179.   /R { /resolveR cvx 3 packedarray cvx } bind    % see Objects below
  180.   /startxref /exit load
  181. .dicttomark readonly def
  182.  
  183. % Because of EOL conversion, lines with fixed contents might be followed
  184. % by one or more blanks.
  185. /lineeq            % <filestr> <conststr> lineeq <bool>
  186.  { anchorsearch
  187.     { pop { ( ) anchorsearch not { () eq exit } if pop } loop }
  188.     { pop false }
  189.    ifelse
  190.  } bind def
  191. /linene { lineeq not } bind def
  192.  
  193. % Read (mostly scan) the cross-reference table.
  194. /readxref        % <pos> readxref <trailerdict>
  195.  { PDFoffset add PDFfile exch setfileposition
  196.         % In some PDF files, this position actually points to
  197.         % white space before the xref line.  Skip over this here.
  198.    { PDFfile fileposition PDFfile read pop 32 gt { exit } if pop
  199.    } loop
  200.    PDFfile exch setfileposition
  201.         % The PDF specification says that the 'xref' must be on a line
  202.         % by itself. The code here formerly used readline and linene to
  203.         % check this. However, Acrobat Reader only requires the line to
  204.         % begin with 'xref', and there are enough applications producing
  205.         % non-compliant PDF files that we have to do this too.
  206.    PDFfile pdfstring 0 4 getinterval readstring pop
  207.    (xref) ne { /readxref cvx /syntaxerror signalerror } if
  208.         % Store the xref table entry position for each object.
  209.         % We only need to read the run headers, not every entry.
  210.     { PDFfile token pop        % first object # or trailer
  211.       dup /trailer eq { pop exit } if
  212.       PDFfile pdfstring readline pop
  213.       token pop            % entry count
  214.       exch pop exch
  215.         % This section might be adding new objects:
  216.         % ensure that Objects and Generations are big enough.
  217.         % Stack: count obj#
  218.       2 copy add growPDFobjects
  219.       PDFfile fileposition 3 -1 roll
  220.        { Objects 2 index lget null eq    % later update might have set it
  221.       { Objects 2 index 2 index cvx lput }
  222.          if exch 1 add exch 20 add
  223.        }
  224.       repeat PDFfile exch setfileposition pop
  225.     } loop
  226.    count /pdfemptycount exch def
  227.    PDFfile traileropdict .pdfrun
  228.  } bind def
  229.  
  230. % Open a PDF file and read the header, trailer, and cross-reference.
  231. /pdfopen {        % <file> pdfopen <dict>
  232.   pdfopenfile begin
  233.   pdfopencache
  234.   .writepdfmarks {
  235.     % Copy bookmarks (outline) to the output.
  236.     Trailer /Root oget /Outlines knownoget {
  237.       /First knownoget {
  238.     { dup writeoutline /Next knownoget not { exit } if } loop
  239.       } if
  240.     } if
  241.   } if        % end .writepdfmarks
  242.   currentdict end
  243. } bind def
  244. /pdfopencache {        % - pdfopencache -
  245.     % Create and initialize some caches.
  246.   /PageCount pdfpagecount def
  247.   /PageNumbers PageCount 65534 .min dict def
  248.   /PageIndex PageCount 65534 .min array def
  249. } bind def
  250. /pdfopenfile {        % <file> pdfopenfile <dict>
  251.    pdfdict readonly pop        % can't do it any earlier than this
  252.    15 dict begin
  253.    /LocalResources 0 dict def
  254.    /DefaultMatrix null def    % establish binding
  255.    /Printed where { pop } {
  256.         % Guess whether the output device is a printer.
  257.      /Printed currentpagedevice /OutputFile known def
  258.    } ifelse
  259.    /PSLevel1 where { pop } { /PSLevel1 false def } ifelse
  260.    cvlit /PDFfile exch def
  261.    /PDFsource PDFfile def
  262.    /Repaired false def
  263.    PDFfile dup 0 setfileposition pdfstring readstring 
  264.    not {/pdfopen cvx /syntaxerror signalerror} if
  265.    (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if
  266.    length /PDFoffset exch def pop cvr /PDFversion exch def
  267.    findxref
  268.    initPDFobjects
  269.     % Read the last cross-reference table.
  270.    readxref /Trailer exch def
  271.    Trailer /Encrypt known
  272.     { pdf_process_Encrypt    % signal error
  273.     }
  274.    if
  275.     % Read any previous cross-reference tables.
  276.    Trailer { /Prev .knownget not { exit } if readxref } loop
  277.    Repaired { printrepaired } if
  278.    currentdict end
  279.  } bind def
  280.  
  281. % Skip backward over the %%EOF at the end of the PDF file, and read
  282. % the preceding startxref line.  The PDF specification unambiguously
  283. % requires that the %%EOF appear on a line by itself, and that the
  284. % startxref and the following position value appear on separate lines;
  285. % however, some applications (including, apparently, Acrobat Distiller
  286. % on the Macintosh) may add up to 2K of garbage after the %%EOF, and some
  287. % other applications also truncate the %%EOF to %%EO, and/or put the
  288. % startxref and the following value on the same line.
  289. % A file reported from Distiller 3.02b for AIX 4.1.1 has 2076 bytes
  290. % of garbage. The tolerance is increased to 4K to cover future
  291. % applications and bigger allocation units.
  292. /findxref {        % - findxref <xrefpos>
  293.   PDFfile dup dup 0 setfileposition bytesavailable
  294.   dup /PDFfilelen exch def
  295.     % Find the last %%EOF string (within 4096 bytes)
  296.   4096 sub PDFoffset .max
  297.   2 copy setfileposition
  298.   PDFfilelen exch sub string 1 index exch readstring pop {
  299.     (\015%%EO) search {        % Adobe can handle truncated key string
  300.       pop pop            % if found, keep searching 'post' string
  301.     } {
  302.       (\012%%EO) search
  303.     { pop pop } { exit } ifelse    % exit if neither string found
  304.     } ifelse
  305.   } loop
  306.   PDFfilelen exch length sub 4 sub PDFoffset .max exch 1 index setfileposition
  307.     % Stack: eofpos
  308.     % Check for whether this is, in fact, a valid PDF file.
  309.   dup PDFfilelen exch sub dup dup 7 gt exch 6 lt or {
  310.     pop true
  311.   } {
  312.     string PDFfile exch readstring pop
  313.     dup (%%EOF\n) eq exch dup (%%EOF\r) eq
  314.     exch (%%EOF\r\n) eq or or not
  315.   } ifelse {
  316.     (
  317.    **** This file has a corrupted %%EOF marker, or garbage after the %%EOF.
  318. ) pdfformaterror
  319.   } if
  320.   PDFfile exch setfileposition
  321.     % Now read the startxref and xref start position.
  322.   prevline token not { null } if dup type /integertype eq {
  323.     exch pop cvi        % xref start position
  324.     exch PDFfile exch setfileposition
  325.     prevline (startxref) linene { /findxref cvx /syntaxerror signalerror } if
  326.     pop
  327.   } {    % else, this file has 'startxref #####' format
  328.     (startxref) ne { /findxref cvx /syntaxerror signalerror } if
  329.     cvi        % xref start position
  330.     (
  331.    **** The format of the startxref line in this file is invalid.
  332. ) pdfformaterror
  333.     exch PDFfile exch setfileposition
  334.   } ifelse
  335. } bind def
  336. /stderrfile (%stderr) (w) file def
  337. /stderrprint {                % <string> stderrprint -
  338.   //stderrfile dup 3 -1 roll writestring flushfile
  339. } bind def
  340. /pdfformaterror {    % <string> pdfformaterror -
  341.   stderrprint
  342.   /Repaired true store
  343. } bind def
  344. /printrepaired {
  345.   Trailer /Info knownoget {
  346.     /Producer knownoget not { null } if
  347.   } {
  348.     null
  349.   } ifelse
  350.   dup null eq {
  351.     pop (\
  352.    **** Please notify the author of the software that produced this file
  353. )
  354.   } {
  355.     (   **** The file was produced by ) stderrprint
  356.     % Handle a Unicode Producer.
  357.     (\376\377) anchorsearch {
  358.       pop dup length 2 idiv string 0 1 2 index length 1 sub {
  359.         % Stack: origstr newstr i
  360.     1 index exch 3 index 1 index 2 mul 1 add get put
  361.       } for exch pop
  362.     } if
  363.     stderrprint
  364.     (:
  365.    **** please notify the author of this software
  366. )
  367.   } ifelse stderrprint
  368. (\
  369.    **** that the file does not conform to Adobe's published PDF
  370.    **** specification.  Processing of the file will continue normally.
  371.  
  372. ) stderrprint
  373. } bind def
  374.  
  375. % Write the outline structure for a file.  Uses linkdest (below).
  376. /writeoutline        % <outlinedict> writeoutline -
  377.  { mark
  378.    0 2 index /First knownoget
  379.     { { exch 1 add exch /Next knownoget not { exit } if } loop }
  380.    if
  381.         % stack: dict mark count
  382.    dup 0 eq
  383.     { pop 1 index
  384.     }
  385.     { 2 index /Count knownoget { 0 lt { neg } if } if
  386.       /Count exch 3 index
  387.     }
  388.    ifelse linkdest /Title oget /Title exch /OUT pdfmark
  389.    /First knownoget
  390.     { { dup writeoutline /Next knownoget not { exit } if } loop }
  391.    if
  392.  } bind def
  393.  
  394. % Close a PDF file.
  395. /pdfclose        % <dict> pdfclose -
  396.  { begin
  397.    PDFfile closefile
  398.    end
  399.  } bind def
  400.  
  401. % ======================== Page accessing ======================== %
  402.  
  403. % Get a (possibly inherited) attribute of a page.
  404. /pget            % <pagedict> <key> pget <value> -true-
  405.             % <pagedict> <key> pget -false-
  406.  { 2 copy knownoget
  407.     { exch pop exch pop true
  408.     }
  409.     { exch /Parent knownoget
  410.        { exch pget }
  411.        { pop false }
  412.       ifelse
  413.     }
  414.    ifelse
  415.  } bind def
  416.  
  417. % Get the value of a resource on a given page.
  418. /rget {            % <resname> <pagedict> <restype> rget <value> -true-
  419.             % <resname> <pagedict> <restype> rget -false-
  420.   LocalResources 1 index knownoget {
  421.      3 index knownoget
  422.   } {
  423.     false
  424.   } ifelse {
  425.     exch pop exch pop exch pop true
  426.   } {
  427.     exch /Resources pget {
  428.       exch knownoget { exch knownoget } { pop false } ifelse
  429.     } {
  430.       pop pop false
  431.     } ifelse
  432.   } ifelse
  433. } bind def
  434.  
  435. % Get the total number of pages in the document.
  436. /pdfpagecount        % - pdfpagecount <int>
  437.  { Trailer /Root oget /Pages oget /Count oget
  438.  } bind def
  439.  
  440. % Find the N'th page of the document by iterating through the Pages tree.
  441. % The first page is numbered 1.
  442. /pdffindpageref {        % <int> pdffindpage <objref>
  443.   dup Trailer /Root oget /Pages get
  444.     {        % We should be able to tell when we reach a leaf
  445.         % by finding a Type unequal to /Pages.  Unfortunately,
  446.         % some files distributed by Adobe lack the Type key
  447.         % in some of the Pages nodes!  Instead, we check for Kids.
  448.       dup oforce /Kids knownoget not { exit } if
  449.       exch pop null
  450.       0 1 3 index length 1 sub {
  451.          2 index exch get
  452.      dup oforce dup /Kids known { /Count oget } { pop 1 } ifelse
  453.         % Stack: index kids null noderef count
  454.      dup 5 index ge { pop exch pop exit } if
  455.      5 -1 roll exch sub 4 1 roll pop
  456.       } for exch pop
  457.         % Stack: index null|noderef
  458.       dup null eq { pop pop 1 null exit } if
  459.     } loop
  460.         % Stack: index countleft noderef
  461.    1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if
  462.    exch pop
  463.    PageIndex 2 index 1 sub 65533 .min 2 index oforce put
  464.    PageNumbers 1 index oforce 3 index dup 65534 le
  465.     { put }
  466.     { pop pop pop }    % don't store more than 65534 pagenumbers
  467.    ifelse
  468.    exch pop
  469. } bind def
  470. /pdffindpage {        % <int> pdffindpage <pagedict>
  471.   pdffindpageref oforce
  472. } bind def
  473.  
  474. % Find the N'th page of the document.
  475. % The first page is numbered 1.
  476. /pdfgetpage        % <int> pdfgetpage <pagedict>
  477.  { PageIndex 1 index 1 sub dup 65533 lt
  478.     { get }
  479.     { pop pop null }
  480.    ifelse
  481.    dup null ne
  482.     { exch pop oforce }
  483.     { pop pdffindpage }
  484.    ifelse
  485.  } bind def
  486.  
  487. % Find the page number of a page object (inverse of pdfgetpage).
  488. /pdfpagenumber        % <pagedict> pdfpagenumber <int>
  489.  {    % We use the simplest and stupidest of all possible algorithms....
  490.    PageNumbers 1 index .knownget
  491.     { exch pop
  492.     }
  493.     { 1 1 PageCount 1 add    % will give a rangecheck if not found
  494.        { dup pdfgetpage oforce 2 index eq { exit } if pop
  495.        }
  496.       for exch pop
  497.     }
  498.    ifelse
  499.  } bind def
  500.  
  501. % Display a given page.
  502. /boxrect        % [<llx> <lly> <urx> <ury>] boxrect <x> <y> <w> <h>
  503.  { aload pop exch 3 index sub exch 2 index sub
  504.  } bind def
  505. /resolvedest {        % <name|string|other> resolvedest <other|null>
  506.   dup type /nametype eq {
  507.     Trailer /Root oget /Dests knownoget {
  508.       exch knownoget not { null } if
  509.     } {
  510.       null
  511.     } ifelse
  512.   } {
  513.     dup type /stringtype eq {
  514.       Trailer /Root oget /Names knownoget {
  515.     /Dests knownoget {
  516.       exch nameoget
  517.     } {
  518.       pop null
  519.     } ifelse
  520.       } {
  521.     pop null
  522.       } ifelse
  523.     } if
  524.   } ifelse
  525. } bind def
  526. /linkdest {        % <link|outline> linkdest
  527.             %   ([/Page <n>] /View <view> | ) <link|outline>
  528.   dup /Dest knownoget
  529.     { resolvedest
  530.       dup type /dicttype eq { /D knownoget not { null } if } if
  531.       dup null eq
  532.        { pop }
  533.        { dup 0 oget
  534.      dup null eq
  535.       { pop }
  536.       { dup type /integertype ne { pdfpagenumber } if
  537.         /Page exch 4 -2 roll
  538.       }
  539.      ifelse
  540.      dup length 1 sub 1 exch getinterval /View exch 3 -1 roll
  541.        }
  542.       ifelse
  543.     }
  544.    if
  545. } bind def
  546. % <pagedict> mark ... -proc- -
  547. /namedactions 8 dict dup begin
  548.   /FirstPage {
  549.     /Page 1 3 -1 roll
  550.   } def
  551.   /LastPage {
  552.     counttomark 2 add index pdfpagecount /Page exch 3 -1 roll
  553.   } def
  554.   /NextPage {
  555.     counttomark 2 add index pdfpagenumber 1 add /Page exch 3 -1 roll
  556.   } def
  557.   /PrevPage {
  558.     counttomark 2 add index pdfpagenumber 1 sub /Page exch 3 -1 roll
  559.   } def
  560. end readonly def
  561. % <pagedict> <annotdict> -proc- -
  562. /annottypes 5 dict dup begin
  563.   /Text {
  564.     mark exch
  565.      { /Rect /Open /Contents }
  566.      { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  567.     forall pop /ANN pdfmark
  568.   } bind def
  569.   /Link {
  570.     mark exch
  571.     dup /C knownoget { /Color exch 3 -1 roll } if
  572.      { /Rect /Border }
  573.      { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
  574.     forall dup /A knownoget {
  575.       dup /URI known {
  576.         /A mark 3 2 roll    % <<>> /A [ <<action>>
  577.         { oforce } forall
  578.         .dicttomark
  579.         3 2 roll
  580.       } {
  581.         dup /D knownoget {
  582.       exch pop exch dup length dict copy dup /Dest 4 -1 roll put
  583.         } {
  584.       /N knownoget {        % Assume /S /Named
  585.          namedactions exch .knownget { exec } if
  586.       } if
  587.         } ifelse
  588.       } ifelse
  589.     } if
  590.     linkdest pop /LNK pdfmark
  591.   } bind def
  592. end readonly def
  593.  
  594. /pdfshowpage        % <pagedict> pdfshowpage -
  595.  { dup /Page exch store
  596.    pdfshowpage_init 
  597.    pdfshowpage_setpage 
  598.    pdfshowpage_finish
  599.  } bind def
  600.  
  601. /pdfpagecontents    % <pagedict> pdfpagecontents <contents>
  602.  { } bind def
  603.  
  604. /pdfshowpage_init     % <pagedict> pdfshowpage_init <pagedict>
  605.  { /DSCPageCount DSCPageCount 1 add store
  606.  } bind def
  607.  
  608. /.pdfshowpage_Install {    % <pagedict> [<prevproc>] .pdfshowpage_Install -
  609.   exch
  610.     % We would like to clip to the CropBox here, but the subsequent
  611.     % initgraphics would override it.  Instead, we have to handle it
  612.     % in graphicsbeginpage.
  613.   dup /CropBox pget dup {exch pop} if systemdict /UseCropBox known and {
  614.     dup /CropBox pget pop dup 0 get neg exch 1 get neg translate
  615.   } {
  616.     dup /MediaBox pget {
  617.       dup 0 get neg exch 1 get neg translate
  618.     } if
  619.   } ifelse
  620.   pop 0 get exec
  621. } bind def
  622.  
  623. /pdfshowpage_setpage {    % <pagedict> pdfshowpage_setpage <pagedict>
  624.   4 dict begin        % for setpagedevice
  625.     % Stack: pagedict
  626.   currentpagedevice /Orientation 2 index /Rotate pget not { 0 } if 90 idiv
  627.     % Rotate specifies *clockwise* rotation!
  628.     neg 3 and def
  629.     % Stack: pagedict currentpagedict
  630.   1 index /CropBox pget dup {exch pop} if systemdict /UseCropBox known and {
  631.             % Set the page size.
  632.     1 index /CropBox pget pop
  633.     boxrect 2 array astore /PageSize exch def pop pop
  634.   } {
  635.     1 index /MediaBox pget {
  636.             % Set the page size.
  637.       boxrect 2 array astore /PageSize exch def pop pop
  638.     } if
  639.   } ifelse
  640.   dup /Install .knownget {
  641.             % Don't let the Install procedure get more deeply
  642.             % nested after every page.
  643.       dup type dup /arraytype eq exch /packedarraytype eq or {
  644.     dup length 4 eq {
  645.       dup 2 get /.pdfshowpage_Install load eq {
  646.         1 get 0 get    % previous procedure
  647.       } if
  648.     } if
  649.       } if
  650.   } {
  651.     { }
  652.   } ifelse 1 array astore
  653.   2 index exch /.pdfshowpage_Install load /exec load
  654.   4 packedarray cvx
  655.     % Stack: pagedict currentpagedict installproc
  656.   /Install exch def
  657.     % Stack: pagedict currentpagedict
  658.   pop currentdict end setpagedevice
  659. } bind def
  660.  
  661. /pdfshowpage_finish {    % <pagedict> pdfshowpage_finish -
  662.    save /PDFSave exch store
  663.    (before exec) VMDEBUG
  664.  
  665.   .writepdfmarks {
  666.  
  667.     % Copy the crop box.
  668.     dup /CropBox knownoget {
  669.     % If the page has been rotated, rotate the CropBox.
  670.       mark /CropBox 3 -1 roll
  671.       3 index /Rotate pget {
  672.     90 idiv 1 and 0 ne {
  673.       aload pop 4 -2 roll exch 4 2 roll exch 4 array astore
  674.     } if
  675.       } if
  676.       /PAGE pdfmark
  677.     } if
  678.  
  679.     % Copy annotations and links.
  680.     dup /Annots knownoget {
  681.       0 1 2 index length 1 sub
  682.        { 1 index exch oget
  683.          dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse
  684.        }
  685.       for pop
  686.     } if
  687.  
  688.   } if        % end .writepdfmarks
  689.  
  690.     % Display the actual page contents.
  691.    6 dict begin
  692.    /BXlevel 0 def
  693.    /BGDefault currentblackgeneration def
  694.    /UCRDefault currentundercolorremoval def
  695.     %****** DOESN'T HANDLE COLOR TRANSFER YET ******
  696.    /TRDefault currenttransfer def
  697.   matrix currentmatrix 2 dict
  698.   2 index /CropBox knownoget {
  699.     boxrect 4 array astore 1 index /ClipRect 3 -1 roll put
  700.   } if
  701.   dictbeginpage /DefaultMatrix 1 index store setmatrix
  702.   dup          % for showing annotations below
  703.   count /pdfemptycount exch store
  704.   gsave
  705.     % If the page uses any transparency features, show it within
  706.     % a transparency group.
  707.   PDFversion 1.4 lt {
  708.     showpagecontents
  709.   } {
  710.     dup pageusestransparency {
  711.       % Show the page within a PDF 1.4 device filter.
  712.       0 .pushpdf14devicefilter {
  713.     % If the page has a Group, enclose contents in transparency group.
  714.         % (Adobe Tech Note 5407, sec 9.2)
  715.         dup /Group knownoget {
  716.       1 index /CropBox knownoget not {
  717.         1 index /MediaBox oget
  718.       } if .beginformgroup {
  719.         showpagecontents
  720.       } .internalstopped {
  721.         .discardtransparencygroup stop
  722.       } if .endtransparencygroup
  723.         } {
  724.       showpagecontents
  725.         } ifelse
  726.       } .internalstopped {
  727.     % todo: discard
  728.     .popdevicefilter stop
  729.       } if .popdevicefilter
  730.     } {
  731.       showpagecontents
  732.     } ifelse
  733.   } ifelse
  734.   grestore
  735.    % todo: mixing drawing ops outside the device filter could cause
  736.    % problems, for example with the pnga device.
  737.    /Annots knownoget { { oforce drawannot } forall } if
  738.    endpage
  739.    end            % scratch dict
  740.    (after exec) VMDEBUG
  741.    PDFSave restore
  742. } bind def
  743. /showpagecontents {    % <pagedict> showpagecontents -
  744.   /Contents knownoget not { 0 array } if
  745.   dup type /arraytype ne { 1 array astore } if {
  746.     oforce false resolvestream pdfopdict .pdfrun
  747.   } forall
  748. } bind def
  749. /processcolorspace {    % - processcolorspace <colorspace>
  750.     % The following is per the PLRM3.
  751.   currentdevice 1 dict dup /ProcessColorModel dup put .getdeviceparams
  752.   exch pop exch pop
  753.   dup type /nametype ne { cvn } if
  754.   dup { setcolorspace } .internalstopped { pop /DeviceRGB } if
  755. } bind def
  756.  
  757. % ------ Transparency support ------ %
  758.  
  759. % Determine whether a page might invoke any transparency features:
  760. %    - Group in the page dictionary
  761. %    - Non-default ca, CA, or SMask in an ExtGState
  762. %    - Form XObject with Group
  763. %    - Image XObject with SMask
  764. % ****** DO WE NEED TO LOOK IN RESOURCE DICTS OF OTHER CONTENT STREAMS? ******
  765. /pageusestransparency {        % <pagedict> pageusestransparency <bool>
  766.   PDFversion 1.4 lt {
  767.     pop false
  768.   } {
  769.     dup /Group known {
  770.       pop true
  771.     } {
  772.       false exch {
  773.     dup resourceusestransparency { pop not exit } if
  774.     /Parent knownoget not { exit } if
  775.       } loop
  776.     } ifelse
  777.   } ifelse
  778. } bind def
  779. % Check the Resources of a page or Form.
  780. /resourceusestransparency {    % <dict> resourceusestransparency <bool>
  781.   {    % Use loop to provide an exitable context.
  782.     /Resources knownoget not { 0 dict } if
  783.     dup /ExtGState knownoget {
  784.       false exch {
  785.     exch pop oforce
  786.     dup /ca knownoget { 1 ne { pop not exit } if } if
  787.     dup /CA knownoget { 1 ne { pop not exit } if } if
  788.     dup /SMask knownoget { /None ne { pop not exit } if } if
  789.     pop
  790.       } forall { pop true exit } if
  791.     } if
  792.     dup /XObject knownoget {
  793.       false exch {
  794.     exch pop oforce dup /Subtype get
  795.     dup /Image eq { 1 index /SMask known { pop pop not exit } if } if
  796.     /Form eq {
  797.       dup /Group known { pop not exit } if
  798.       resourceusestransparency { not exit } if
  799.     } {
  800.       pop
  801.     } ifelse
  802.       } forall { pop true exit } if
  803.     } if
  804.     pop false exit
  805.   } loop
  806. } bind def
  807.  
  808. end            % pdfdict
  809. .setglobal
  810.